package com.elong.qadev.tool;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import com.elong.qadev.entity.Entities;
import com.elong.qadev.entity.Header;
import com.elong.qadev.entity.NameValuePair;
import com.elong.qadev.entity.UrlParam;
/**
 * 
* @ClassName: HttpClient
* @Description: TODO(http请求的基础类)
* @author kangchen
* @date 2015年9月30日
*
 */
public class HttpClient {

	private final CloseableHttpClient httpclient;
	private final RequestConfig requestConfig;
	private HttpRequestBase requestBase;
	private CloseableHttpResponse response;

	public HttpClient() {
		httpclient = HttpClients.createDefault();
		requestConfig = RequestConfig.custom()
				.setConnectionRequestTimeout(30000).setConnectTimeout(30000)
				.setSocketTimeout(30000).build();
	}
	/**
	 * 
	* @Title: assemble
	* @Description: TODO(组装HTTP请求)
	* @param @param httpUrl
	* @param @param httpMethod
	* @param @param headers
	* @param @param urlParams
	* @param @param entities
	* @param @param nameValuePairs
	* @param @return
	* @param @throws Exception    参数
	* @return String    返回类型
	* @throws
	 */
	public String assemble(String httpUrl, String httpMethod,
			ArrayList<Header> headers, ArrayList<UrlParam> urlParams,
			Entities entities, ArrayList<NameValuePair> nameValuePairs)
			throws Exception {
		URI uri = getURI(httpUrl, urlParams);
		if (httpMethod.equalsIgnoreCase("GET")) {
			requestBase = new HttpGet(uri);
		} else if (httpMethod.equalsIgnoreCase("POST")) {
			HttpPost httpPost = new HttpPost(uri);
			httpPost.setEntity(getEntity(entities, nameValuePairs));
			requestBase = httpPost;
		} else if (httpMethod.equals("DELETE")) {
			requestBase = new HttpDelete(uri);
		} else if (httpMethod.equals("PUT")) {
			HttpPut httpPut = new HttpPut(uri);
			httpPut.setEntity(getEntity(entities, nameValuePairs));
			requestBase = httpPut;
		} else {
			throw new IllegalArgumentException(String.format(
					"Unsupported http method %s!", httpMethod));
		}
		if (null != headers) {
			for (int i = 0; i < headers.size(); ++i) {
				Header header = (Header) headers.get(i);
				String key = header.getKey();
				String value = header.getValue();
				requestBase.setHeader(key, value);
			}
		}
		requestBase.setConfig(requestConfig);
		return requestBase.getRequestLine().toString();
	}
	
	/**
	 * 
	* @Title: send
	* @Description: TODO(发送请求获取返回结果的实体内容)
	* @param @return
	* @param @throws Exception    参数
	* @return String    返回类型
	* @throws
	 */
	public String send() throws Exception {
		try {
			response = httpclient.execute(requestBase);
			return IOUtils.toString(response.getEntity().getContent(), "UTF-8");
		} finally {
			if (null != response) {
				response.close();
			}
		}
	}

	public int getStatusCode() throws Exception {
		return response.getStatusLine().getStatusCode();
	}

	public void close() throws Exception {
		httpclient.close();
	}

	public HttpRequestBase getRequest() {
		return requestBase;
	}

	public CloseableHttpResponse getResponse() {
		return response;
	}

	public CloseableHttpClient getHttpClient() {
		return httpclient;
	}
	
	/**
	 * 
	* @Title: getURI
	* @Description: TODO(组装请求地址)
	* @param @param httpUrl
	* @param @param urlParams
	* @param @return
	* @param @throws Exception    参数
	* @return URI    返回类型
	* @throws
	 */
	private URI getURI(String httpUrl, ArrayList<UrlParam> urlParams)
			throws Exception {
		String hostPort = httpUrl;
		String schema = "http";
		if (httpUrl.startsWith("http://")) {
			hostPort = httpUrl.substring("http://".length());
		} else if (httpUrl.startsWith("https://")) {
			hostPort = httpUrl.substring("https://".length());
			schema = "https";
		}
		String path = "/";
		int index = hostPort.indexOf("/");
		if (-1 != index) {
			path = hostPort.substring(index);
			hostPort = hostPort.substring(0, index);
		}
		String[] hostPortSplit = hostPort.split(":");
		String host = hostPort;
		int port = 80;
		if (2 == hostPortSplit.length) {
			host = hostPortSplit[0];
			port = Integer.parseInt(hostPortSplit[1]);
		}

		URIBuilder builder = new URIBuilder();
		builder.setScheme(schema).setHost(host).setPort(port).setPath(path);
		if (null != urlParams) {
			for (int i = 0; i < urlParams.size(); ++i) {
				UrlParam urlParam = (UrlParam) urlParams.get(i);
				String key = urlParam.getKey();
				String value = urlParam.getValue();
				if (null != value) {
					builder.addParameter(key, value);
				}
			}
		}
		URI uri = builder.build();
		return uri;
	}
	/**
	 * 
	* @Title: getEntity
	* @Description: TODO(根据设置返回请求实体body)
	* @param @param entities
	* @param @param nameValuePairs
	* @param @return
	* @param @throws Exception    参数
	* @return HttpEntity    返回类型
	* @throws
	 */
	private HttpEntity getEntity(Entities entities,
			ArrayList<NameValuePair> nameValuePairs) throws Exception {
		if (null == entities) {
			return null;
		}
		if ("x-www-form-urlencoded".equals(entities.getType())) {
			try {
				List<BasicNameValuePair> basicNameValuePairs = new ArrayList<BasicNameValuePair>();
				for (int i = 0; i < nameValuePairs.size(); ++i) {
					NameValuePair nameValuePair = (NameValuePair) nameValuePairs
							.get(i);
					String key = nameValuePair.getKey();
					String value = nameValuePair.getValue();
					basicNameValuePairs.add(new BasicNameValuePair(key, value));
				}
				return new UrlEncodedFormEntity(basicNameValuePairs, "UTF-8");
			} catch (IOException ex) {
				return null;
			}
		} else {
			StringEntity entity = new StringEntity(entities.getData()
					.toString(), "UTF-8");
			entity.setContentType("application/json");
			return entity;
		}
	}
}
